`timescale 1ns/1ns

module tb_sm4_core ;
reg clock;
reg rst_n;

initial begin
    clock = 1'b0;
    forever begin
        #5 clock = ~clock;
    end
end

initial begin
    rst_n = 1'b0;
    #20 rst_n = 1'b1;
end


reg [127:0] MK;
reg [127:0] plaintext;
reg [1:0] mode;
wire key_ex_finished;
wire data_ready;
wire [127:0] ciphertext;
reg key_valid;
reg data_valid;

initial begin
    sm4_init;
    #1000;
    sm4_key_ext(128'h0123456789ABCDEFFEDCBA9876543210);
    
    while(key_ex_finished != 1'b1) begin
        @(posedge clock);
    end
    key_valid = 1'b0;
    //
    //wait_finished(key_valid,key_ex_finished);
    #500;
    sm4_enc(128'h0123456789ABCDEFFEDCBA9876543210);
    while(data_ready!=1'b1) begin
      @(posedge clock);
    end
    data_valid = 1'b0;
    #500;
    sm4_dec(ciphertext);
    #10;
    while(data_ready!=1'b1) begin
      @(posedge clock);
    end
    data_valid = 1'b0;
    #1000;
    $finish;
end


SM4_Core SM4_Core_0(
    .clk_i(clock),
    .rst_n_i(rst_n),
    
    .MK_Valid_i(key_valid),
    .Key_i(MK),
    .Data_Valid_i(data_valid),
    .Data_i(plaintext),
    .mode_i(mode),      //00:密钥拓展 11：加密 01：解密
    .RK_Ready_o(key_ex_finished),
    .Data_Ready_o(data_ready),
    .Data_o(ciphertext) 
);

//veri------
wire [127:0] enc_ref = 128'h681e_df34_d206_965e_86b3_e94f_536e_4246;
wire [127:0] dec_ref = 128'h0123_4567_89ab_cdef_fedc_ba98_7654_3210;
always@(data_ready or data_valid) begin
  #1;
  if((data_ready==1'b1) && (data_valid==1'b1)) begin
    $display("INFO: Data processing finished. @",$realtime);
    //#1;
    if(mode == 2'd3 && ciphertext == enc_ref) begin
      $display("INFO: ENCRYPTO SUCCESS!");
    end
    else if(mode == 2'd1 && ciphertext == dec_ref) begin
      $display("INFO: DECRYPTO SUCCESS!");
    end
    else begin
      $display("INFO: VERIFICATE FALID!");
      $display("mode = %d",mode);
      $display("MK = %h", MK);
      $display("data_input = %h", plaintext);
      $display("data_output = %h", ciphertext);
    end
  end
end

task sm4_init;
  begin
    key_valid = 1'b0;
    data_valid = 1'b0;
    MK = 128'b0;
    plaintext = 128'b0;
    mode = 2'b10;
  end
endtask

task sm4_key_ext;
    input [127:0] key_in;    
    begin
        key_valid = 1'b1;
        MK = key_in;
        mode = 2'b00;        
    end
endtask

task sm4_enc;
    input [127:0] data_in;
    begin
        data_valid = 1'b1;
        plaintext = data_in;
        mode = 2'b11;
    end
endtask

task sm4_dec;
    input [127:0] data_in;
    begin
        data_valid = 1'b1;
        plaintext = data_in;
        mode = 2'b01;
    end
endtask

endmodule //tb_sm4_core